package com.statistics.service.supplementary.thread;

import com.statistics.entity.PressForMoneyDto;
import com.statistics.entity.SupplementDto;
import com.statistics.entity.YhSupplementDto;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 多线程填补缺失的数据
 * @author hewei
 * @date 2022/6/29 16:33
 * @Description
 */
@Slf4j
public class SupplementaryCallable implements Callable<Map<String, List<SupplementDto>>> {
    /**
     *  需要填补的数据
     */
    private Map<String, List<PressForMoneyDto>> availableData;

    /**
     *  需要填补的数据
     */
    private Map<String, YhSupplementDto> yhData;




    public SupplementaryCallable(Map<String, List<PressForMoneyDto>> availableData,Map<String, YhSupplementDto> yhData) {
        this.availableData = availableData;
        this.yhData = yhData;
    }

    @Override
    public Map<String, List<SupplementDto>> call() {
        Iterator<Map.Entry<String, List<PressForMoneyDto>>> iterator = availableData.entrySet().iterator();
        // 外面循环 按照身份证姓名循环，为一组单独的数据 重新循环
        Map<String, List<SupplementDto>> map = new ConcurrentHashMap<>();
        while (iterator.hasNext()){
            final String key = iterator.next().getKey();
            List<PressForMoneyDto> press = availableData.get(key);
            final YhSupplementDto yhSupplementDto = yhData.get(key);
            // 开始填补的时间
            final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime startDate = LocalDateTime.parse("2019-03-01 00:00:00",dateTimeFormatter);
            List<SupplementDto> list = new LinkedList<>();
            // 内层循环 为 根据身份证补齐信息的循环
            do {
                LocalDateTime localDateTime = startDate.plusWeeks(2);
                // 补充时间已超过一年 所有号码设置已停机
                LocalDateTime finalStartDate1 = startDate;
                // 判断 解析出来的数据集合 时间在 执行到的时间 之后的数据等于0条 则执行添加新增停机状态数据方法
                if (null == press || press.stream().filter(l -> LocalDateTime.parse(l.getResultDate(), dateTimeFormatter).isAfter(finalStartDate1)).count() == 0){
                    list.add(this.createStatistics(yhSupplementDto,dateTimeFormatter.format(this.createRandomDate(startDate,localDateTime))));
                    list.add(this.createStatistics(yhSupplementDto,dateTimeFormatter.format(this.createRandomDate(startDate,localDateTime))));
                }else {
                    // 判断时间是否在时间为半月的时间之内 有则不必新增  没有则添加数据
                    LocalDateTime finalStartDate = startDate;
                    // 当当前半月之中存在2条数据，则不需要在重复添加数据 一条就补一条 没有就补2条
                    List<PressForMoneyDto> excelData  = press.stream().filter(pres -> isBetween(finalStartDate, localDateTime, LocalDateTime.parse(pres.getResultDate(), dateTimeFormatter))).collect(Collectors.toList());
                    if (excelData.isEmpty()) {
                        list.add(this.createStatistics(yhSupplementDto,dateTimeFormatter.format(this.createRandomDate(startDate,localDateTime)),getLiaisonResult()));
                        list.add(this.createStatistics(yhSupplementDto,dateTimeFormatter.format(this.createRandomDate(startDate,localDateTime)),getLiaisonResult()));
                    }else if (excelData.size() == 1){
                        list.add(this.createStatistics(yhSupplementDto,dateTimeFormatter.format(this.createRandomDate(startDate,localDateTime)),getLiaisonResult()));
                    }
                }
                startDate = localDateTime;
            }while (LocalDateTime.now().isAfter(startDate));
            map.put(yhSupplementDto.getIdCard(),list);
            iterator.remove();
            log.info(Thread.currentThread().getName());
        }
        return map;
    }

    public static void main(String[] args) {
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startDate = LocalDateTime.parse("2019-03-01 00:00:00",dateTimeFormatter);
        List<SupplementDto> list = new ArrayList<>();
        final SupplementDto build1 = SupplementDto.builder().resultDate("2019-03-01 00:00:00").build();
        final SupplementDto build2 = SupplementDto.builder().resultDate("2019-03-02 00:00:00").build();
        final SupplementDto build3 = SupplementDto.builder().resultDate("2019-03-03 00:00:00").build();
        final SupplementDto build4 = SupplementDto.builder().resultDate("2019-03-04 00:00:00").build();
        final SupplementDto build5 = SupplementDto.builder().resultDate("2019-03-05 00:00:00").build();
        final SupplementDto build6 = SupplementDto.builder().resultDate("2019-03-06 00:00:00").build();
        list.add(build1);
        list.add(build2);
        list.add(build3);
        list.add(build4);
        list.add(build5);
        list.add(build6);
        final long count = list.stream().filter(l -> LocalDateTime.parse(l.getResultDate(), dateTimeFormatter).isAfter(LocalDateTime.now())).count();
        System.out.println(count);
    }

    /**
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @param excelData 判断的执行时间
     * @return true在时间段内，false不在时间段内
     */
    public boolean isBetween(LocalDateTime beginTime, LocalDateTime endTime,LocalDateTime excelData) {
        boolean flag = false;
        // 判断执行在开始时间之后 并且 在结束时间之前
        if (excelData.isAfter(beginTime) && excelData.isBefore(endTime)) {
            flag = true;
        }
        return flag;
    }

    /**
     * 前一年的数据 生成
     * @param yhSupplementDto
     * @param resultDate
     * @return
     */
    public SupplementDto createStatistics(YhSupplementDto yhSupplementDto, String resultDate,int liaisonResult){
        return SupplementDto.builder()
                .name(yhSupplementDto.getName())
                .CardNumber(yhSupplementDto.getAccount())
                .idCard(yhSupplementDto.getIdCard())
                .phone(yhSupplementDto.getPhone())
                .relationship("本人")
                .liaisonResult(liaisonResult + "")
                .result(getResult(liaisonResult)+"")
                .resultDate(resultDate)
                .resultMode("电话催收")
                .resultContent(getRecord(liaisonResult))
                .resultStatus(getResult(liaisonResult)+"")
                .build();
    }

    /**
     * 后2年年的数据 生成
     * @param yhSupplementDto
     * @param resultDate
     * @return
     */
    public SupplementDto createStatistics(YhSupplementDto yhSupplementDto, String resultDate){
        return SupplementDto.builder()
                .name(yhSupplementDto.getName())
                .CardNumber(yhSupplementDto.getAccount())
                .idCard(yhSupplementDto.getIdCard())
                .phone(yhSupplementDto.getPhone())
                .relationship("本人")
                .liaisonResult(6 + "")
                .result(8+"")
                .resultDate(resultDate)
                .resultMode("电话催收")
                .resultContent(getRecord(6))
                .resultStatus(8+"")
                .build();
    }

    /**
     * 一个时间段内随机一个时间
     * @param startTime
     * @param endTime
     * @return
     */
    public LocalDateTime createRandomDate(LocalDateTime startTime, LocalDateTime endTime){
        //将两个时间转为时间戳
        long start = startTime.toEpochSecond(ZoneOffset.of("+8"));
        long end = endTime.toEpochSecond(ZoneOffset.of("+8"));
        //获取两个时间的随机数
        long difference = (long)(Math.random() * (end - start));
        //生成时间
        return LocalDateTime.ofEpochSecond(start+difference,0, ZoneOffset.ofHours(8));
    }


    public String getRecord(int number){
        switch (number){
            case 2:
                return "通话中";
            case 3:
                return "无人接听";
            case 4:
                return "关机";
            case 5:
                return "拒接";
            case 6:
                return "已停机";
            case 7:
                return "无法接通";
            case 8:
                return "完成协催  短信申请";
            default:
                return "正忙";
        }
    }

    /**
     * 催收结果
     * @return
     */
    public int getResult(int result){
        switch (result) {
            case 2:
            case 5:
                return 6;
            case 3:
                return 7;
            case 4:
            case 6:
            case 7:
                return 8;
            case 8:
            default:
                return 9;
        }
    }


    /**
     * 联络结果
     * @return
     */
    public int getLiaisonResult(){
        Random random = new Random();
        int liaisonResult;
        do {
            liaisonResult = random.nextInt(8);
        }while (liaisonResult == 0 || liaisonResult ==1 || liaisonResult ==6);
        return liaisonResult;
    }
}
